

#include "cybertron/core/UtilDirectory.hpp"
#include "cybertron/core/UtilString.hpp"
#include "cybertron/core/UtilPath.hpp"
#include "../PlatformHeader.hpp"

#ifndef CYBERTRON_WIN 
  #include <sys/stat.h>
  #include <dirent.h> 
  #include <cstring>
  #include <stdlib.h>
#endif

CYBERTRON_BEGIN

CybertronCoreAPI bool UtilDirectory::exist(const std::string& dirName)
{
#ifdef CYBERTRON_WIN
	std::wstring dirNameW = UtilString::u2w(dirName);

	WIN32_FIND_DATAW fndData;
	HANDLE hFind = FindFirstFileW(dirNameW.c_str(), &fndData);

	bool found = false;
	if (hFind != INVALID_HANDLE_VALUE && (fndData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
	{
		found = true;
	}

	if (hFind != INVALID_HANDLE_VALUE && hFind != NULL)
	{
		FindClose(hFind);
	}

	return found;
#else
	struct stat sb;
	if (stat(dirName.c_str(), &sb) == 0 && S_ISDIR(sb.st_mode))
		return true;
	else
		return false;
#endif
}

CybertronCoreAPI bool UtilDirectory::create(const std::string& dirName)
{
#ifdef CYBERTRON_WIN
	std::wstring inputPathW;
	try
	{
		std::wstring_convert<std::codecvt_utf8<wchar_t>> utf8_conv;
		inputPathW = utf8_conv.from_bytes(dirName);
	}
	catch (const std::exception &)
	{
		inputPathW.clear();
	}

	if (inputPathW.size() > 0)
	{
		CreateDirectoryW(inputPathW.c_str(), NULL);
	}
	else
	{
		CreateDirectoryA(dirName.c_str(), NULL);
	}
#else
	mkdir(dirName.c_str(), 0755);
#endif

	return true;
}

CybertronCoreAPI bool UtilDirectory::createMultipleDirectory(const std::string& dirName)
{
	std::string command;
#ifdef CYBERTRON_WIN
	command = "mkdir " + dirName;
#else
	command = "mkdir -p " + dirName;
#endif
	system(command.c_str());
	return true;
}

CybertronCoreAPI bool UtilDirectory::getFiles(
	std::vector<std::string>& files,
	const std::string& dirName)
{
	files.clear();

#ifdef CYBERTRON_WIN
	std::string pattern = UtilPath::combine(dirName, "*");
	std::wstring patternW = UtilString::u2w(pattern);

	WIN32_FIND_DATAW fndData;
	HANDLE hFind = FindFirstFileW(patternW.c_str(), &fndData);
	while (hFind != INVALID_HANDLE_VALUE && hFind != NULL)
	{
		if ((fndData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
		{
			files.push_back(UtilString::w2u(fndData.cFileName));
		}
		if (!FindNextFileW(hFind, &fndData))
		{
			break;
		}
	}

	if (hFind != INVALID_HANDLE_VALUE && hFind != NULL)
	{
		FindClose(hFind);
	}

	return true;
#else
	DIR* dir = opendir(dirName.c_str());
	if (!dir)
		return false;
	struct dirent* pEnt = NULL;
	while ((pEnt = readdir(dir)) != NULL)
	{
		if (pEnt->d_type == DT_REG)
			files.push_back(pEnt->d_name);
	}
	return true;
#endif
}

CybertronCoreAPI bool UtilDirectory::getFolders(
	std::vector<std::string>& folders,
	const std::string& dirName)
{
	folders.clear();

#ifdef CYBERTRON_WIN
	std::string pattern = UtilPath::combine(dirName, "*");
	std::wstring patternW = UtilString::u2w(pattern);

	WIN32_FIND_DATAW fndData;
	HANDLE hFind = FindFirstFileW(patternW.c_str(), &fndData);
	while (hFind != INVALID_HANDLE_VALUE && hFind != NULL)
	{
		if ((fndData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
		{
			folders.push_back(UtilString::w2u(fndData.cFileName));
		}
		if (!FindNextFileW(hFind, &fndData))
		{
			break;
		}
	}

	if (hFind != INVALID_HANDLE_VALUE && hFind != NULL)
	{
		FindClose(hFind);
	}

	return true;
#else
	DIR* dir = opendir(dirName.c_str());
	if (!dir)
		return false;
	struct dirent* pEnt = NULL;
	while ((pEnt = readdir(dir)) != NULL)
	{
		if (pEnt->d_type == DT_DIR)
			folders.push_back(pEnt->d_name);
	}
	return true;
#endif
}


CybertronCoreAPI std::string UtilDirectory::getTempFolder()
{
	std::string tmpFolder;

#ifdef CYBERTRON_WIN
	std::vector<TCHAR> collapsed_path;
	size_t copied = MAX_PATH;
	
	collapsed_path.resize(copied);
	copied = GetTempPath((DWORD)collapsed_path.size(), collapsed_path.data());
	if (copied < collapsed_path.size()) {
		std::vector<TCHAR> full_path;
		copied = MAX_PATH;

		full_path.resize(copied);
		copied = GetLongPathName(collapsed_path.data(), full_path.data(), (DWORD)full_path.size());
		if (copied < full_path.size()) {
			std::string path(std::begin(full_path), std::end(full_path));
			// trim whitespace at the end of string
			const char* str = path.c_str();
			tmpFolder = str;
		}
	}
#else
        char const *folder = getenv("TMPDIR");
	if (folder == 0)
	    folder = "/tmp";

	tmpFolder = folder;
#endif

	return tmpFolder;
}

CYBERTRON_END
